from django.shortcuts import render
from rest_framework import viewsets, status
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.decorators import action
from django.db.models import Count, Q
from django.utils import timezone
import subprocess
import platform
import re
import logging

from .models import City, DataCenter, Host, HostCredential, HostStatistics
from .serializers import (
    CitySerializer, DataCenterSerializer, HostSerializer, 
    HostCredentialSerializer, HostStatisticsSerializer, PingResultSerializer
)

logger = logging.getLogger(__name__)


class CityViewSet(viewsets.ModelViewSet):
    """城市管理视图集"""
    queryset = City.objects.all().order_by('name')
    serializer_class = CitySerializer
    
    def get_queryset(self):
        queryset = City.objects.all()
        name = self.request.query_params.get('name')
        if name:
            queryset = queryset.filter(name__icontains=name)
        return queryset.order_by('name')


class DataCenterViewSet(viewsets.ModelViewSet):
    """机房管理视图集"""
    queryset = DataCenter.objects.select_related('city').all()
    serializer_class = DataCenterSerializer
    
    def get_queryset(self):
        queryset = DataCenter.objects.select_related('city').all()
        city_id = self.request.query_params.get('city_id')
        name = self.request.query_params.get('name')
        
        if city_id:
            queryset = queryset.filter(city_id=city_id)
        if name:
            queryset = queryset.filter(name__icontains=name)
            
        return queryset.order_by('city__name', 'name')


class HostViewSet(viewsets.ModelViewSet):
    """主机管理视图集"""
    queryset = Host.objects.select_related('datacenter__city').all()
    serializer_class = HostSerializer
    
    def get_queryset(self):
        queryset = Host.objects.select_related('datacenter__city').all()
        
        # 查询参数过滤
        datacenter_id = self.request.query_params.get('datacenter_id')
        city_id = self.request.query_params.get('city_id')
        status_filter = self.request.query_params.get('status')
        ip_address = self.request.query_params.get('ip_address')
        hostname = self.request.query_params.get('hostname')
        
        if datacenter_id:
            queryset = queryset.filter(datacenter_id=datacenter_id)
        if city_id:
            queryset = queryset.filter(datacenter__city_id=city_id)
        if status_filter:
            queryset = queryset.filter(status=status_filter)
        if ip_address:
            queryset = queryset.filter(ip_address__icontains=ip_address)
        if hostname:
            queryset = queryset.filter(hostname__icontains=hostname)
            
        return queryset.order_by('hostname')

    @action(detail=True, methods=['post'])
    def ping(self, request, pk=None):
        """单个主机ping探测"""
        host = self.get_object()
        result = self._ping_host(host)
        
        # 更新主机ping结果
        host.last_ping_time = result['ping_time']
        host.last_ping_result = result['is_reachable']
        host.save(update_fields=['last_ping_time', 'last_ping_result'])
        
        serializer = PingResultSerializer(result)
        return Response(serializer.data)

    @action(detail=False, methods=['post'])
    def ping_all(self, request):
        """批量ping探测"""
        # 获取查询参数
        datacenter_id = request.query_params.get('datacenter_id')
        city_id = request.query_params.get('city_id')
        
        queryset = self.get_queryset()
        if datacenter_id:
            queryset = queryset.filter(datacenter_id=datacenter_id)
        if city_id:
            queryset = queryset.filter(datacenter__city_id=city_id)
        
        results = []
        for host in queryset:
            result = self._ping_host(host)
            results.append(result)
            
            # 更新主机ping结果
            host.last_ping_time = result['ping_time']
            host.last_ping_result = result['is_reachable']
            host.save(update_fields=['last_ping_time', 'last_ping_result'])
        
        serializer = PingResultSerializer(results, many=True)
        return Response({
            'total': len(results),
            'reachable': len([r for r in results if r['is_reachable']]),
            'unreachable': len([r for r in results if not r['is_reachable']]),
            'results': serializer.data
        })

    def _ping_host(self, host):
        """执行ping操作"""
        ping_time = timezone.now()
        
        try:
            # 根据操作系统选择ping命令
            if platform.system().lower() == 'windows':
                cmd = ['ping', '-n', '1', '-w', '3000', host.ip_address]
            else:
                cmd = ['ping', '-c', '1', '-W', '3', host.ip_address]
            
            result = subprocess.run(cmd, capture_output=True, text=True, timeout=5)
            
            is_reachable = result.returncode == 0
            response_time = None
            error_message = None
            
            if is_reachable:
                # 从ping输出中提取响应时间
                if platform.system().lower() == 'windows':
                    # Windows ping输出格式
                    match = re.search(r'时间[<=](\d+)ms', result.stdout) or \
                            re.search(r'time[<=](\d+)ms', result.stdout)
                else:
                    # Linux/Unix ping输出格式
                    match = re.search(r'time=(\d+\.?\d*).*ms', result.stdout)
                
                if match:
                    response_time = float(match.group(1))
            else:
                error_message = result.stderr or result.stdout
                
        except subprocess.TimeoutExpired:
            is_reachable = False
            response_time = None
            error_message = "Ping timeout"
        except Exception as e:
            logger.error(f"Ping error for {host.ip_address}: {str(e)}")
            is_reachable = False
            response_time = None
            error_message = str(e)
        
        return {
            'host_id': host.id,
            'hostname': host.hostname,
            'ip_address': host.ip_address,
            'is_reachable': is_reachable,
            'response_time': response_time,
            'ping_time': ping_time,
            'error_message': error_message
        }


class HostCredentialViewSet(viewsets.ModelViewSet):
    """主机凭证管理视图集"""
    queryset = HostCredential.objects.select_related('host').all()
    serializer_class = HostCredentialSerializer
    
    def get_queryset(self):
        queryset = HostCredential.objects.select_related('host').all()
        host_id = self.request.query_params.get('host_id')
        if host_id:
            queryset = queryset.filter(host_id=host_id)
        return queryset.order_by('host__hostname')



class HostStatisticsViewSet(viewsets.ReadOnlyModelViewSet):
    """主机统计只读视图集"""
    queryset = HostStatistics.objects.select_related('city', 'datacenter').all()
    serializer_class = HostStatisticsSerializer

    def get_queryset(self):
        queryset = HostStatistics.objects.select_related('city', 'datacenter').all()

        city_id = self.request.query_params.get('city_id')
        datacenter_id = self.request.query_params.get('datacenter_id')
        date_from = self.request.query_params.get('date_from')
        date_to = self.request.query_params.get('date_to')

        if city_id:
            queryset = queryset.filter(city_id=city_id)
        if datacenter_id:
            queryset = queryset.filter(datacenter_id=datacenter_id)
        if date_from:
            queryset = queryset.filter(statistics_date__gte=date_from)
        if date_to:
            queryset = queryset.filter(statistics_date__lte=date_to)

        return queryset.order_by('-statistics_date', 'city__name', 'datacenter__name')

    @action(detail=False, methods=['post'])
    def generate_stats(self, request):
        """生成今天的统计数据"""
        statistics_date = timezone.now().date()

        # 删除当天已有统计数据
        HostStatistics.objects.filter(statistics_date=statistics_date).delete()

        # 按城市和机房分组统计主机状态
        stats_data = Host.objects.values(
            'datacenter__city_id',
            'datacenter_id'
        ).annotate(
            total=Count('id'),
            online=Count('id', filter=Q(status='online')),
            offline=Count('id', filter=Q(status='offline')),
            maintenance=Count('id', filter=Q(status='maintenance'))
        )

        # 创建统计记录
        stats_records = []
        for stat in stats_data:
            if stat['total'] > 0:  # 只有当有主机时才创建记录
                record = HostStatistics(
                    city_id=stat['datacenter__city_id'],
                    datacenter_id=stat['datacenter_id'],
                    total_hosts=stat['total'],
                    online_hosts=stat['online'],
                    offline_hosts=stat['offline'],
                    maintenance_hosts=stat['maintenance'],
                    statistics_date=statistics_date
                )
                stats_records.append(record)

        # 批量创建记录
        if stats_records:
            HostStatistics.objects.bulk_create(stats_records)
            return Response({
                'message': f'成功生成 {len(stats_records)} 条统计记录',
                'date': statistics_date
            })
        else:
            return Response({
                'message': '没有主机数据，未生成统计记录',
                'date': statistics_date
            })
